home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 8357 < prev    next >
Encoding:
Text File  |  1996-08-05  |  3.8 KB  |  88 lines

  1. Newsgroups: comp.lang.c
  2. Path: news.sprintlink.net!eskimo!scs
  3. From: scs@eskimo.com (Steve Summit)
  4. Subject: Re: more problems with qsort
  5. X-Nntp-Posting-Host: eskimo.com
  6. Message-ID: <DnpBFK.7nv@eskimo.com>
  7. Sender: news@eskimo.com (News User Id)
  8. Organization: schmorganization
  9. References: <4h0j9e$ng5@clarknet.clark.net> <4h81m0$avr@solutions.solon.com> <4hba5n$2ga@clarknet.clark.net>
  10. Date: Sun, 3 Mar 1996 17:04:30 GMT
  11.  
  12. In article <4hba5n$2ga@clarknet.clark.net>, yom@clark.net writes:
  13. > In article <4h81m0$avr@solutions.solon.com>, seebs@solutions.solon.com 
  14. > says...
  15. >> In article <4h0j9e$ng5@clarknet.clark.net>, yom <yom@clark.net> wrote:
  16. >> >And your compare function must be defined like this:
  17. >> >int compare(char **a,char **b) {return strcmp(*a,*b);}
  18. >>
  19. >> No, it really mustn't.  It must be defined like this:
  20. >> int compare(const void *a, const void *b) {
  21. >>        return strcmp(*(char **) a, *(char **) b);
  22. >> }
  23. > Well I disagree on this one. Results of 1) defining the compare 
  24. > function that takes two char** arguments and casting the function call 
  25. > to qsort and 2) defining the compare function that takes two void* 
  26. > arguments and casting the arguments to char ** in strcmp call are
  27. > identical.
  28.  
  29. The *results* *on your system* may have been identical, but the
  30. two code fragments most certainly are not.
  31.  
  32. If I may take the liberty of quoting from "C Programming FAQs:
  33. Frequently Asked Questions", Addison-Wesley, 1996:
  34.  
  35.     To understand why the curious pointer conversions in a qsort
  36.     comparison function are necessary (and why a cast of the
  37.     function pointer when calling qsort() can't help), it's useful
  38.     to think about how qsort() works.  qsort() doesn't know
  39.     anything about the type or representation of the data being
  40.     sorted: it just shuffles around little chunks of memory.
  41.     (All it knows about the chunks is their size, which you
  42.     specify in qsort()'s third argument.)  To determine whether
  43.     two chunks need swapping, qsort() calls your comparison
  44.     function.  (To swap them, it uses the equivalent of memcpy().)
  45.  
  46.     Since qsort() deals in a generic way with chunks of memory of
  47.     unknown type, it uses generic pointers (void *) to refer to
  48.     them.  When qsort() calls your comparison function, it passes
  49.     as arguments two generic pointers to the chunks to be
  50.     compared.  Since it passes generic pointers, your comparison
  51.     function must *accept* generic pointers, and convert the
  52.     pointers back to their appropriate type before manipulating
  53.     them (i.e. before performing the comparison).  A void pointer
  54.     is not the same type as a structure pointer, and on some
  55.     machines it may have a different size or representation
  56.     (which is why these casts are required for correctness).
  57.  
  58.     If you were sorting an array of structures, and had a
  59.     comparison function accepting structure pointers:
  60.  
  61.         int mywrongstructcmp(struct mystruct *, struct mystruct *);
  62.  
  63.     and if you called qsort() as
  64.  
  65.         qsort(dates, ndates, sizeof(struct mystruct),
  66.             (int (*)(const void *, const void *))mywrongstructcmp);
  67.                                 /* WRONG */
  68.  
  69.     the cast (int (*)(const void *, const void *)) would do
  70.     nothing except perhaps silence the message from the compiler
  71.     telling you that this comparison function may *not* work with
  72.     qsort().  The implications of any cast you use when calling
  73.     qsort will have been forgotten by the time qsort() gets around
  74.     to calling your comparison function: it will call them with
  75.     const void * arguments, so that is what your function must
  76.     accept.  No prototype mechanism exists which could operate
  77.     down inside qsort() to convert the void pointers to struct
  78.     mystruct pointers just before calling mywrongstructcmp().
  79.  
  80.     In general, it is a bad idea to insert casts just to "shut the
  81.     compiler up."  Compiler warnings are usually trying to tell
  82.     you something, and unless you really know what you're doing,
  83.     you ignore or muzzle them at your peril.  See also question 4.9.
  84.  
  85.                         Steve Summit
  86.                         scs@eskimo.com
  87.